import json
import logging

from django.utils import timezone
from django.db.models import Q
from django.http import JsonResponse
from rest_framework.views import APIView

from monitor_alert_center.models import MonitorGroup, MonitorTask, AlertContactPerson, AlertContactGroup, \
    AlertContactPersonGroup, AlertLogs, MonitorTaskAlertGroup

from utils.page_data import PageData
from utils.redis_task import publish_task_operation
from utils.check_permission import check_permission
from utils.run_task_and_send_alert_msg import RunTaskAndSendAlertMsg

logger = logging.getLogger()
# 修改权限
logger.setLevel(logging.INFO)


class MonitorGroupActionView(APIView):
    """监控分组操作"""

    @check_permission(perms_list=['alert:contactGroup:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def delete(self, request):
        """删除分组"""
        data = json.loads(request.body.decode("utf-8"))
        try:
            group_id = data['groupID']
            user_id = request.session.get('user_id')
            role_list = request.session.get('role_list')
            MonitorGroup.objects.filter(id=group_id, sysrolemonitorgroup__role_id__in=role_list).delete()
        except Exception as e:
            logger.error(e)
            if 'because they are referenced through protected foreign keys' in str(e):
                return JsonResponse({"code": 500, "msg": f"该分组中还有监控任务，请先删除监控任务"})
            return JsonResponse({"code": 500, "msg": f"删除分组失败：{str(e)}"})
        return JsonResponse({"code": 200})

    def post(self, request):
        """添加和修改分组"""
        data = json.loads(request.body.decode("utf-8"))
        group_name = data['name']
        sort_num = data['sort_num']

        try:
            if data['id'] == -1:
                MonitorGroup.objects.create(name=group_name, sort_num=sort_num)
            else:
                MonitorGroup.objects.filter(id=data['id']).update(name=group_name, sort_num=sort_num)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"操作分组失败：{str(e)}"})
        return JsonResponse({"code": 200})

    def get(self, request):
        try:
            role_list = request.session.get('role_list')
            mon_group_obj = (MonitorGroup.objects.filter(sysrolemonitorgroup__role_id__in=role_list)
                             .order_by('sort_num').values('id', 'name', 'sort_num'))

            for group in list(mon_group_obj):
                group["count"] = MonitorTask.objects.filter(mon_group_id=group['id']).count()

            type_choices = MonitorTask.type_choices
            type_data = [{'id': id, 'name': name} for id, name in type_choices]

            alert_method_choices = MonitorTask.alert_method_choices
            alert_method_data = [{'id': id, 'name': name} for id, name in alert_method_choices]
        except Exception as e:
            return JsonResponse({'code': 500, 'msg': f"获取监控分组失败：{e}"})
        return JsonResponse({'code': 200, 'group_msg': list(mon_group_obj), 'type_msg': type_data,
                             'alert_method_msg': alert_method_data})


class MonitorTaskActionView(APIView):
    """任务管理功能"""

    @check_permission(perms_list=['monitor:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.__run_task_and_send_alert_msg = RunTaskAndSendAlertMsg()

    def get(self, request):
        try:
            task_id = request.GET.get("task_id")
            if task_id:
                task_queryset = MonitorTask.objects.filter(id=task_id).values()
                recv_alert_groups_obj = AlertContactGroup.objects.filter(
                    monitortaskalertgroup__monitor_task_id=task_id).values_list('id')
                group_list = [i[0] for i in recv_alert_groups_obj]
                return JsonResponse({"code": 200, "msg": list(task_queryset), "group": group_list})

            # 当前页
            page_num = request.GET.get("pageNum")
            # 每页大小
            page_size = request.GET.get("pageSize")
            task_name = request.GET.get("name")
            enable_status = int(request.GET.get("enableStatus"))
            groups_id = request.GET.get("groupID")
            type_id = request.GET.get("typeID")

            role_list = request.session.get('role_list')

            mon_group_role_obj = MonitorGroup.objects.filter(sysrolemonitorgroup__role_id__in=role_list).all()

            query_criteria = Q()
            query_criteria &= Q(mon_group__in=mon_group_role_obj)
            if task_name:
                query_criteria &= Q(name__contains=task_name)
            if enable_status == 1 or enable_status == 2:
                query_criteria &= Q(enable_status=enable_status)
            if groups_id and groups_id != 'undefined':
                query_criteria &= Q(mon_group__id=groups_id)
            if type_id and type_id != 'undefined':
                query_criteria &= Q(type=type_id)
            task_queryset = (MonitorTask.objects.filter(query_criteria).order_by('sort_num')
                             .values('id', 'enable_status', 'task_status', 'mon_group__name',
                                     'type', 'name', 'mon_path', 'mon_freq', 'remark', 'update_time',
                                     'alert_method_list', 'sort_num'))
            type_choices = MonitorTask.type_choices
            alert_method_choices = MonitorTask.alert_method_choices
            # 创建一个字典来映射 type 值到对应的汉字描述
            type_mapping = dict(type_choices)
            alert_method_mapping = dict(alert_method_choices)

            # 使用PageData 类，获取分页数据
            task_list_obj = PageData(task_queryset, page_size, page_num)
            task_list = task_list_obj.get_search()
            for item in task_list:
                try:
                    item['update_time'] = item['update_time'].strftime('%Y-%m-%d %H:%M:%S')
                except AttributeError as e:
                    logger.error(str(e))
                item['type'] = type_mapping[item['type']]
                for i in range(len(item['alert_method_list'])):
                    if item['alert_method_list'][i] in alert_method_mapping:
                        item['alert_method_list'][i] = alert_method_mapping[item['alert_method_list'][i]]
            total = task_queryset.count()
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"获取任务失败：{str(e)}"})
        return JsonResponse({"code": 200, "total": total, "msg": task_list})

    def delete(self, request):
        try:
            data = json.loads(request.body.decode("utf-8"))
            task_id = data.get('taskID')

            task_obj = MonitorTask.objects.filter(id=task_id)
            # 发布禁用操作
            publish_task_operation('disable', task_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"删除任务失败：{str(e)}"})
        task_obj.delete()
        return JsonResponse({"code": 200})

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        try:
            active_id = int(request.GET.get("activeID"))
            # active_id == 1:新增/修改 ,active_id == 2:禁用/启用
            if active_id == 1:
                mon_group_id = data['mon_group_id']
                name = data['name']
                types = data['type']
                mon_freq = data['mon_freq']
                mon_path = data['mon_path']
                sort_num = data['sort_num']

                host_id = None
                timeout = None
                if types == 3 or types == 4:
                    host_id = data.get('host_id')
                else:
                    timeout = data['timeout']

                trigger_threshold = data['trigger_threshold']
                recv_alert_group = data['recv_alert_group']
                alert_method_list = data['alert_method_list']
                quiet_time = data['quiet_time'][0]
                remark = data['remark']
                enable_status = data.get('enable_status')

                enable_status = enable_status or 1

                add = 0
                if request.GET.get("add"):
                    add = int(request.GET.get("add"))

                if add == 1:
                    mon_task_obj = MonitorTask(enable_status=enable_status, mon_group_id=mon_group_id,
                                               type=types, name=name, mon_path=mon_path, timeout=timeout,
                                               mon_freq=mon_freq, trigger_threshold=trigger_threshold,
                                               alert_method_list=alert_method_list, sort_num=sort_num,
                                               quiet_time=quiet_time, remark=remark, host_id=host_id)

                    mon_task_obj.save()
                    mon_task_obj = MonitorTask.objects.filter(name=name).get()
                    task_id = mon_task_obj.id

                    if recv_alert_group:
                        for item in recv_alert_group:
                            MonitorTaskAlertGroup.objects.create(monitor_task_id=task_id, alert_group_id=item)

                    # 发布启用用操作
                    publish_task_operation('enable', task_id)
                else:
                    task_id = data.get('id')

                    # 如果选择了告警联系组，则先删除该task_id以前的，监控任务与告警联系组的关联表数据，
                    # 再新增监控任务与告警联系组的关联表数据
                    if recv_alert_group:
                        MonitorTaskAlertGroup.objects.filter(monitor_task_id=task_id).delete()
                        for item in recv_alert_group:
                            MonitorTaskAlertGroup.objects.create(monitor_task_id=task_id, alert_group_id=item)

                    (MonitorTask.objects.filter(id=task_id)
                     .update(enable_status=enable_status, mon_group_id=mon_group_id,
                             type=types, name=name, mon_path=mon_path, timeout=timeout,
                             mon_freq=mon_freq, trigger_threshold=trigger_threshold,
                             alert_method_list=alert_method_list, host_id=host_id, sort_num=sort_num,
                             quiet_time=quiet_time, remark=remark, update_time=timezone.now()))

                    if int(enable_status) == 1:
                        # 发布启用用操作
                        publish_task_operation('enable', task_id)
                    else:
                        # 发布禁用操作
                        publish_task_operation('disable', task_id)
            # == 2:禁用/启用
            else:
                task_id = data.get('taskID')
                task_obj = MonitorTask.objects.filter(id=task_id)

                if task_obj.get().enable_status == 1:
                    task_obj.update(enable_status=2, num_of_fail=0, task_status=0)
                    # 发布禁用操作
                    publish_task_operation('disable', task_id)
                else:
                    task_obj.update(enable_status=1)

                    # 发布启用用操作
                    publish_task_operation('enable', task_id)
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"操作任务失败：{str(e)}"})
        return JsonResponse({"code": 200})


class CheckPersonView(APIView):
    """检测联系人是否重名"""

    @check_permission(perms_list=['alert:contactPerson:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']

        if not AlertContactPerson.objects.filter(name=name).exists():
            return JsonResponse({"code": 200})
        return JsonResponse({"code": 500, "msg": f"获取新增告警联系人失败"})


class PersonListView(APIView):
    """获取告警联系人列表"""

    @check_permission(perms_list=['alert:contactPerson:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        if not data.get('pageNum'):
            alert_person_obj = AlertContactPerson.objects.values()
            return JsonResponse({"code": 200, "msg": list(alert_person_obj)})

        # 当前页
        page_num = data.get("pageNum")
        # 每页大小
        page_size = data.get("pageSize")
        query = data.get("query")
        try:
            query_criteria = Q()
            if query:
                query_criteria &= Q(name__contains=query)

            alert_person_obj = AlertContactPerson.objects.filter(query_criteria).values()
            # 使用PageData 类，获取分页数据
            person_list_obj = PageData(alert_person_obj, page_size, page_num)
            person_list = person_list_obj.get_search()

        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"获取告警联系人失败：{str(e)}"})
        return JsonResponse({"code": 200, "msg": person_list, "total": alert_person_obj.count()})


class PersonActionView(APIView):
    """告警联系人操作"""

    @check_permission(perms_list=['alert:contactPerson:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        person_id = data['id']
        name = data['name']
        phone_number = data.get('phone_number', '')
        email = data.get('email', '')
        feishu_bot = data.get('feishu_bot', '')
        feishu_bot_sign = data.get('feishu_bot_sign', '')
        ding_talk = data.get('ding_talk', '')
        ding_talk_sign = data.get('ding_talk_sign', '')
        qw_id = data.get('qw_id', '')
        qw_robot_secret = data.get('qw_robot_secret', '')
        qw_agent_id = data.get('qw_agent_id', '')
        qw_to_user = data.get('qw_to_user', '')
        create_time = data.get('create_time', '')
        try:
            if person_id == -1:
                person_obj = AlertContactPerson(name=name, phone_number=phone_number, email=email,
                                                feishu_bot=feishu_bot, feishu_bot_sign=feishu_bot_sign,
                                                ding_talk=ding_talk, ding_talk_sign=ding_talk_sign,
                                                qw_id=qw_id, qw_robot_secret=qw_robot_secret,
                                                qw_agent_id=qw_agent_id, qw_to_user=qw_to_user)
                person_obj.save()
            else:
                person_obj = AlertContactPerson(id=person_id, name=name, phone_number=phone_number,
                                                email=email, feishu_bot=feishu_bot, feishu_bot_sign=feishu_bot_sign,
                                                ding_talk=ding_talk, ding_talk_sign=ding_talk_sign, qw_id=qw_id,
                                                qw_robot_secret=qw_robot_secret, qw_agent_id=qw_agent_id,
                                                qw_to_user=qw_to_user, create_time=create_time)
                person_obj.save()
        except Exception as e:
            logger.error(f"告警联系人操作失败：{e}")
            return JsonResponse({"code": 500, "msg": f"告警联系人操作失败：{str(e)}"})
        return JsonResponse({"code": 200})

    def get(self, request):
        person_id = request.GET.get('id')
        try:
            person_obj = AlertContactPerson.objects.filter(id=person_id).values().first()
        except Exception as e:
            logger.error(f"告警联系人操作失败：{e}")
            return JsonResponse({"code": 500, "msg": f"告警联系人操作失败：{str(e)}"})
        return JsonResponse({"code": 200, "msg": person_obj})

    def delete(self, request):
        data = json.loads(request.body.decode("utf-8"))
        person_id = data['personID']
        try:
            AlertContactPerson.objects.filter(id=person_id).delete()
        except Exception as e:
            logger.error(f"删除告警联系人失败：{e}")
            return JsonResponse({"code": 500, "msg": f"删除告警联系人失败：{str(e)}"})
        return JsonResponse({"code": 200})


class GroupListView(APIView):
    """获取告警联系组列表"""

    @check_permission(perms_list=['alert:contactGroup:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        # 当前页
        page_num = data.get("pageNum")
        # 每页大小
        page_size = data.get("pageSize")
        query = data.get("query")
        try:
            if not data.get('pageNum'):
                group_list = AlertContactGroup.objects.values('id', 'name')
                return JsonResponse({"code": 200, "msg": list(group_list)})

            query_criteria = Q()
            if query:
                query_criteria &= Q(name__contains=query)

            alert_group_obj = AlertContactGroup.objects.filter(query_criteria).values()
            # 使用PageData 类，获取分页数据
            group_list_obj = PageData(alert_group_obj, page_size, page_num)
            group_list = group_list_obj.get_search()
            for item in group_list:
                item['person_num'] = (AlertContactPerson.objects
                                      .filter(alertcontactpersongroup__group_id=item['id']).count())
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"获取告警联系组失败：{str(e)}"})
        return JsonResponse({"code": 200, "msg": group_list, "total": alert_group_obj.count()})


class CheckGroupView(APIView):
    """检测联系组是否重名"""

    @check_permission(perms_list=['alert:contactGroup:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        name = data['name']

        if not AlertContactGroup.objects.filter(name=name).exists():
            return JsonResponse({"code": 200})
        return JsonResponse({"code": 500, "msg": f"获取新增告警联系组失败"})


class GroupActionView(APIView):
    """告警联系组操作"""

    @check_permission(perms_list=['alert:contactGroup:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        group_id = data['id']
        name = data['name']
        remark = data.get('remark', '')
        create_time = data.get('create_time', '')
        person_list = data.get('personListData', '')
        try:
            if group_id == -1:
                group_obj = AlertContactGroup.objects
                group_obj.create(name=name, remark=remark)

                group_id = group_obj.filter(name=name).get().id
                for item in person_list:
                    AlertContactPersonGroup.objects.create(person_id=item, group_id=group_id)
            else:
                group_obj = AlertContactGroup(id=group_id, name=name, remark=remark,
                                              create_time=create_time)
                group_obj.save()

                AlertContactPersonGroup.objects.filter(group_id=group_id).delete()

                for item in person_list:
                    AlertContactPersonGroup.objects.create(person_id=item, group_id=group_id)
        except Exception as e:
            logger.error(f"告警联系组操作失败：{e}")
            return JsonResponse({"code": 500, "msg": f"告警联系组操作失败：{str(e)}"})
        return JsonResponse({"code": 200})

    def get(self, request):
        group_id = request.GET.get('id')
        try:
            group_obj = AlertContactGroup.objects.filter(id=group_id).values().first()

            person_list = AlertContactPersonGroup.objects.filter(group_id=group_id).values()

            group_obj['personListData'] = []
            for item in person_list:
                group_obj['personListData'].append(item['person_id'])

        except Exception as e:
            logger.error(f"告警联系组操作失败：{e}")
            return JsonResponse({"code": 500, "msg": f"告警联系组操作失败：{str(e)}"})
        return JsonResponse({"code": 200, "msg": group_obj})

    def delete(self, request):
        data = json.loads(request.body.decode("utf-8"))
        group_id = data['groupID']
        try:
            AlertContactGroup.objects.filter(id=group_id).delete()
        except Exception as e:
            logger.error(f"删除告警联系组失败：{e}")
            return JsonResponse({"code": 500, "msg": f"删除告警联系组失败：{str(e)}"})
        return JsonResponse({"code": 200})


class AlertLogsView(APIView):
    """告警记录"""

    @check_permission(perms_list=['alert:logs:list'])  # 直接应用装饰器，无需method_decorator
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request):
        data = json.loads(request.body.decode("utf-8"))
        # 当前页
        page_num = data.get("pageNum")
        # 每页大小
        page_size = data.get("pageSize")
        alert_name = data.get("alertName")
        group_name = data.get("groupName")
        type_name = data.get("typeName")
        status_id = data.get("statusID")
        try:
            query_criteria = Q()
            if alert_name:
                query_criteria &= Q(alert_name__name__contains=alert_name)
            if group_name:
                query_criteria &= Q(mon_group=group_name)
            if type_name:
                query_criteria &= Q(type=type_name)
            if int(status_id) < 2:
                query_criteria &= Q(alert_status=int(status_id))
            if int(status_id) == 3:
                alert_logs_obj_num = AlertLogs.objects.filter(query_criteria).count()

            role_list = request.session.get('role_list')
            mon_group_role_obj = MonitorGroup.objects.filter(sysrolemonitorgroup__role_id__in=role_list).all()
            task_obj = MonitorTask.objects.filter(mon_group__in=mon_group_role_obj).all()
            query_criteria &= Q(name__in=task_obj)

            alert_logs_obj = (AlertLogs.objects.filter(query_criteria).order_by('-id')
                              .values("name__name", "mon_group", "type", "mon_path",
                                      "alert_status", "recv_alert_group", "duration_time", "first_alert_time"))
            # 使用PageData 类，获取分页数据
            logs_obj = PageData(alert_logs_obj, page_size, page_num)
            logs_list = logs_obj.get_search()
            for item in logs_list:
                try:
                    item['first_alert_time'] = item['first_alert_time'].strftime('%Y-%m-%d %H:%M:%S')
                except AttributeError as e:
                    logger.error(str(e))
        except AttributeError as e:
            logger.error(str(e))
        except Exception as e:
            logger.error(e)
            return JsonResponse({"code": 500, "msg": f"获取告警联系人失败：{str(e)}"})
        return JsonResponse({"code": 200, "msg": logs_list, "total": alert_logs_obj.count()})
